import logging
import sqlite3
import time
from datetime import datetime, timedelta
from threading import Thread

import uvicorn
from fastapi import FastAPI
from fastapi.responses import FileResponse
from starlette.middleware.cors import CORSMiddleware
from starlette.staticfiles import StaticFiles

from db import init_db
from view.plateView import plates_router
from view.recognizeView import recognize_router

app = FastAPI()

app.include_router(recognize_router)
app.include_router(plates_router, prefix="/plates")

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

app.mount("/server_manager", StaticFiles(directory="server_manager"), name="server_manager")

# ---------------------- 定时器核心逻辑 ----------------------
# 全局定时器控制变量
def check_abnormal_plates(max_stay_hours=24):
    """检测滞留超时的车辆并标记为异常"""
    try:
        conn = sqlite3.connect('./license_plates.db')
        c = conn.cursor()

        # 计算滞留时间阈值（当前时间 - 最长允许时长）
        threshold_time = datetime.now() - timedelta(hours=max_stay_hours)

        # 查询当前在场且入场时间早于阈值的车辆
        c.execute('''
                  SELECT plate_number, enter_time, location, filename
                  FROM current_plates
                  WHERE enter_time < ?
                  ''', (threshold_time.strftime('%Y-%m-%d %H:%M:%S'),))

        abnormal_records = c.fetchall()

        if not abnormal_records:
            logging.info("当前无异常车辆")
            return

        # 处理每辆异常车辆
        for record in abnormal_records:
            plate_num, enter_time, location, filename = record
            try:
                # 检查是否已存在异常记录（避免重复报警）
                c.execute('''
                          SELECT id
                          FROM abnormal_plates
                          WHERE plate_number = ?
                          ''', (plate_num,))
                existing = c.fetchone()

                if existing is None:
                    # 插入新异常记录
                    c.execute('''
                              INSERT INTO abnormal_plates (plate_number, enter_time, location, filename)
                              VALUES (?, ?, ?, ?)
                              ''', (plate_num, enter_time, location, filename))
                    c.execute('''
                              DELETE FROM current_plates WHERE plate_number = ?
                              ''', (plate_num,))
                    logging.warning(f"检测到异常车辆：{plate_num}，已滞留超{max_stay_hours}小时")

            except sqlite3.Error as e:
                logging.error(f"处理{plate_num}时数据库出错：{str(e)}")
                conn.rollback()
                continue

        conn.commit()
        logging.info(f"本次检测到{len(abnormal_records)}辆异常车辆")

    except Exception as e:
        logging.error(f"检测异常车辆时发生未知错误：{str(e)}")
    finally:
        if 'conn' in locals():
            conn.close()
timer_running = False
timer_interval = 60*60*24  # 检测间隔（秒），默认1Day
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

def run_timer():
    """定时器线程主函数"""
    global timer_running
    timer_running = True
    logging.info(f"定时器启动，检测间隔：{timer_interval} 秒")

    while timer_running:
        try:
            # 执行异常车辆检测（可传入参数，如最长允许停留时长）
            check_abnormal_plates(max_stay_hours=24)  # 检测滞留超24小时的车辆
        except Exception as e:
            logging.error(f"定时器执行出错：{str(e)}")

        # 等待下一次检测
        time.sleep(timer_interval)

    logging.info("定时器已停止")


# ---------------------- 应用生命周期事件 ----------------------
@app.on_event("startup")
async def startup_event():
    """应用启动时自动初始化数据库并启动定时器"""
    logging.info("应用启动，正在初始化数据库...")
    init_db()  # 初始化数据库表结构

    logging.info("正在启动异常车辆检测定时器...")
    # 创建定时器线程（守护线程，主程序退出时自动终止）
    timer_thread = Thread(target=run_timer, daemon=True)
    timer_thread.start()


@app.on_event("shutdown")
async def shutdown_event():
    """应用关闭时停止定时器（可选）"""
    global timer_running
    if timer_running:
        timer_running = False
        logging.info("定时器已停止")
    logging.info("应用关闭")

@app.get("/")
@app.get("/manager")
async def manager():
    # 返回 index.html 文件
    return FileResponse("server_manager/index.html")


if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)
